package com.example.warehouseplus.webflux.handler;

import com.example.warehouseplus.security.AuthRequest;
import com.example.warehouseplus.security.AuthResponse;
import com.example.warehouseplus.service.impl.UserService;
import com.example.warehouseplus.utils.JWTUtil;
import com.example.warehouseplus.utils.Limiting;
import com.example.warehouseplus.utils.PBKDF2Encoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

@Slf4j
@Component
public class AuthenticationHandler {

	@Autowired
	private JWTUtil jwtUtil;

	@Autowired
	private PBKDF2Encoder passwordEncoder;

	@Autowired
	private UserService userService;

	@Limiting(limitNum = 0.5, name = "loginLimiter")
	public Mono<ServerResponse> login(ServerRequest request) {
		log.info("Processing login request");
		return request.bodyToMono(AuthRequest.class)
				.flatMap(ar -> userService.findByUsername(ar.getUsername())
						.filter(userDetails -> passwordEncoder.encode(ar.getPassword()).equals(userDetails.getPassword()))
						.map(userDetails -> {
							log.info("User {} authenticated successfully", ar.getUsername());
							return new AuthResponse(jwtUtil.generateToken(userDetails));
						})
						.flatMap(authResponse -> ServerResponse.ok()
								.contentType(MediaType.APPLICATION_JSON)
								.bodyValue(authResponse))
						.switchIfEmpty(Mono.defer(() -> {
							log.info("Authentication failed for user {}", ar.getUsername());
							return ServerResponse.status(HttpStatus.UNAUTHORIZED).build();
						}))
				);
	}
}
